小厂面试,恐怖如斯。。。
大家好,今天分享 编程导航星球 的一位鱼友面试 Java 开发的面试题记录,虽然是小厂,但题目还是有些难度的,大家可以感受一下,看看自己能答出多少~
星球原文链接:https://t.zsxq.com/0cZyVf6J0
本文已获得 hezefeng 同学授权
小公司个人面试题记录
Java 开发工程师
有不同答案,欢迎各位大佬提出!
Q1:字符串如何实现反转
A1:
用StringBuffer或StringBuilder自带的reverse方法。
Q2:什么是Java序列化
A2:
序列化:把Java对象转换为字节序列(二进制流)的过程。为了解决对象流进行读写操作或网络传输时所引发的问题。
反序列化:把字节序列(二进制流)恢复为Java对象的过程。
Q3:Array和ArrayList的区别
A3:
可以将ArrayList想象成一种“会自动扩增容量的Array”。
1.Array类型的变量在声明的同时必须进行实例化(需初始化数组的大小);而ArrayList只需要声明。
2.Array始终是连续存放;而ArrayList的存放不一定连续。
3.Array对象的初始化必须指定大小,切创建后的数组大小是固定的;而ArrayList的大小可以动态指定,空间大小可以自动扩增。4.Array不能随意在任意位置添加、删除数据;而ArrayList可以在任意位置插入、删除数据。
5.Array比ArrayList效率高。
Q4:抽象类和接口的区别
A4:
1.一个子类只能继承一个抽象类,但能实现多个接口。
2.抽象类可以有构造方法,接口没有构造方法。
3.抽象类可以有普通成员变量,接口没有。
4.抽象类和接口都可以静态成员变量,抽象类中静态成员变量访问类型任意,接口只能public static final(默认)。
5.抽象类可以没有抽象方法,抽象类可以有普通方法;接口在JDK8之前都是抽象方法,在JDK8可以有default方法,在JDK9中允许有私有普通方法。
6.抽象类可以有静态方法;接口在JDK8之前不能有静态方法,在JDK8中可以有静态方法,且只能被接口类直接调用(不能被实现类的对象调用)。
7.抽象类中的方法可以是public、protevted;接口在JDK8之前只有public abstract,在JDK8可以有default方法,在JDK9中允许有private方法。
Q5:like会导致索引失效吗(MySQL)
A5:
like以%开头,索引失效;当like前缀没有%,后缀有%时,索引有效。解决索引失效,可以使用覆盖索引。
想了解覆盖索引首先需要了解主键索引和辅助索引。
主键索引:叶子结点保存的是数据;
辅助索引:叶子结点保存的是主键值。
回表:由于辅助索引保存的是主键值,如果使用辅助索引搜索数据就必须先从辅助索引取到主键值,再使用主键的值去主键索引上查询,直到找到叶子结点上的数据返回。
覆盖索引:辅助索引的叶子结点直接保存的是我们需要的数据,则称为覆盖索引。
Q6:什么样的数据表字段需要创建索引
A6:
创建索引的情况:主键自动创建唯一索引;频繁作为查询条件的字段;外键关系字段;参与排序的字段;分组依据的字段;组合查询的字段。
不创建索引的情况:在表中出现次数少的字段;经常增删改的字段;where几乎不参与的字段;过滤性不好的字段。
Q7:如何提高数据库查询效率
A7:
1.应尽量避免全表扫描,应先考虑在where或order by涉及的列上建立索引。(可以使用explain关键词对SQL语句性能分析)
2.应尽量避免在where子句中对字段进行null值判断。
3.并非所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,查询可能不会去利用索引。
4.尽量使用数字型字段,若只含数值信息的字段,尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次即可。
5.尽可能使用varchar/nvarchar代替char/nchar,因为可变长类型字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高。
Q8:redis缓存击穿解决方法
A8:
缓存穿透指的是缓存查询的key不存在,数据库也无数据。
解决方法:
1.接口增加不合法的参数校验。预防调用方恶意传一些不可能存在的数据。
2.DB中查询不到数据的情况,可以将该key对应的value设为null值,或其他特殊值,同时设置短一点的过去时间,以免影响正常情况。该方法可以防止短时间内同一个key进行暴力攻击。
3.若只是恶意者故意攻击,可以在nginx配置对攻击者ip设置访问阈值。
4.布隆过滤器,利用高效的数据结构和算法快速判断该key是否存在数据库,不存在就return,存在就去查询DB数据库刷新KV再return。
缓存击穿指的是缓存无数据,数据库有数据,key比较集中。
解决方法:
1.设置热点数据永不过期。
2.热点数据快过期时,通过另一个异步线程重新设置key。
3.当缓存数据过期,重新从数据库加载数据到缓存的过程上互斥锁。
Q9:redis缓存雪崩解决方法
A9:
缓存雪崩指的是缓存集合在同一时间段内过期失效或某原因缓存服务器发生宕机,导致大量的缓存击穿,所有请求直接访问数据库。
解决方法:
1.使用缓存集群,保证缓存高可用。
2.使用Hystrix,通过熔断、降级、限流三个手段降低雪崩后发生的损失。
3.设置不同的过期时间。
4.数据预热。在正式部署前,先把可能的数据预先访问一遍,将可能被访问到的数据提前加载到缓存。
Q10:redis有哪些拒绝策略(淘汰策略)
A10:
有8中淘汰策略:
1.volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
2.volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
3.volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
4.volatile-lfu:从已设置过期时间的数据集中挑选使用频率最低的数据淘汰。
5.allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
6.allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
7.allkeys- random:从数据集中任意选择数据淘汰。
8.no-enviction(驱逐):原有的数据不进行删除,达到缓存最大内存时,直接返回错误信息。这也是redis默认的淘汰策略。
Q11:redisson分布式锁的缺点
A11:
1.redis宕机或网络不稳定时导致死锁。
2.如果redis缓存架构是redis cluster或redis master- slave,则可能会出现加锁的redis master故障,刚好数据也还没有同步到slave。导致其他客户端来尝试加锁,新的master给另一个客户端加锁后,这时候就会出现两个客户端同时被加锁,从而导致业务语义出现问题和可能产生各种脏数据。
Q12:redis和数据库如何保证一致性
A12:
1.延迟双删策略:删除缓存-更新数据库-休眠一段时间-再次删除缓存。休眠是为了在更新完数据库前保证读请求结束,此时读请求的数据是脏数据,然后再一次删除缓存。
2.异步更新缓存(基于订阅binlog的同步机制):使用canal框架,将redis伪装成mysql的slave节点进行备份请求,从而达到redis缓存更新。
Q13:使用SpringCloud的原因,有什么优点
A13:
SpringCloud产出于Spring大家族,Spring在企业级开发框架无人能敌,可以保证后续的更新、完善组件,功能齐全。SpringCloud为微服务架构提供了非常完整的支持。SpringCloud社区活跃度高,服务拆分粒度细,耦合度低。有利于资源重复利用,提高开发效率,提高系统的可维护性,可以并行开发,减轻团队开发成本。
Q14:RabbitMq优缺点
A14:
优点:1.应用解耦。提升容错性和可维护性
2.异步提速。提升用户体验和系统吞吐量
3.削峰填谷。提高系统稳定性
缺点:1.系统可用性降低。可能出现mq服务宕机
2.系统复杂度提高。可能出现重复消费,消息丢失等问题
3.一致性问题。消费消息时服务出现问题,导致数据不一致
Q15:RabbitMq消息阻塞怎么解决
A15:
消息阻塞出现的原因是RabbitMQ提供了一种QOS(服务质量保证)功能,即在非自动确认消息的前提下,限制信道上的消费者所能保持的最大未确认的数量(可以通过prefetchCount属性设置)。可以理解为consumer前面加了一个缓冲容器,容器最大容量是prefetchCount。当缓冲容器等于prefetchCount时,RabbitMQ则不再进行投递,导致消息阻塞。
解决方法:将consumer消费消息的代码放进try catch代码块中,若出现异常将消息重新投放到队列中,没有异常则手动确认消费,避免消息一直阻塞在缓冲容器里。
Q16:如何解决RabbitMq重复消费
A16:
1.消费端处理消息的业务逻辑保持幂等性。
2.保证每条消息都有唯一编号(消息ID)且保证消息处理成功与去重表的日志同时出现。利用一张日志表记录已经处理成功的消息ID。
Q17:两台手机同时支付同一笔订单,如何防止订单重复支付
A17:
支付接口对同一笔订单进行加锁处理,对支付逻辑做幂等性处理。进入支付逻辑,优先查询订单状态,如果支付成功或支付中状态则不执行下面支付逻辑。如果是第一次进来支付,则先将订单设置为支付中状态,可以防止支付成功或失败回调慢而导致用户进行第二次支付。
Q18:HashTable和HashMap的区别
A18:
1.底层数据结构不同,jdk1.7底层都是数组+链表,但jdk1.8HashMap加入了红黑树。
2.HashTable不允许键或值为null,HashMap键值都可以为null。
3.添加key- value的hash值算法不同:HashMap使用自定义的哈希算法。HashTable采用key的hashCode方法。
4.实现方式不同:HashTable继承Dictionary类,HashMap继承AbstractMap类。
5.初始化容量不同:HashMap的初始容量为16,HashTable为11。两者的负载因子默认都是0.75。
6.扩容机制不同:当已用容量>总容量*负载因子时,HashMap扩容规则为当前容量翻倍,HashTable扩容规则为当前容量翻倍+1。
7.支持的遍历种类不同:HashMap只支持Iterator遍历,而HashTable支持Iterator和Enumeration两种方式遍历。
8.迭代器不同:HashMap的迭代器是fail-fast,而HashTable的enumerator迭代器不是fail-fast。
9.部分API不同:HashMap不支持contains(Object value)方法,没有重写toString()方法,而HashTable支持contains(Object value)方法,而且重写了toString()方法。
10.同步性不同:HashTable是同步的,适合于多线程环境,而HashMap不是同步的,适用于单线程环境。多个线程可以共享一个HashTable,而如果没有正确的同步的话,多个线程是不能共享HashMap的。
11.由于HahsTable是线程安全的,所以在单线程环境下比HashMap慢。
星球活动
1.欢迎参与 30 天面试题挑战活动 ,搞定高频面试题,斩杀面试官!
2.欢迎已加入星球的同学 免费申请一年编程导航网站会员 !
3.欢迎学习 鱼皮最新原创项目教程,手把手教你做出项目、写出高分简历!
加入我们
欢迎加入鱼皮的编程导航知识星球,鱼皮会 1 对 1 回答您的问题、直播带你做出项目、为你定制学习计划和求职指导,还能获取海量编程学习资源,和上万名学编程的同学共享知识、交流进步。
💎 加入星球后,您可以:
1)添加鱼皮本人微信,向他 1 对 1 提问,帮您解决问题、告别迷茫!点击了解详情
2)获取海量编程知识和资源,包括:4000+ 鱼皮的编程答疑和求职指导、原创编程学习路线、几十万字的编程学习知识库、几十 T 编程学习资源、700+ 精华帖等!点击了解详情
3)找鱼皮咨询求职建议和优化简历,次数不限!点击了解详情
4)鱼皮直播从 0 到 1 带大家做出项目,已有 50+ 直播、完结 4 套项目、10+ 项目分享,帮您掌握独立开发项目的能力、丰富简历!点击了解详情
外面一套项目课就上千元了,而星球内所有项目都有指导答疑,轻松解决问题
星球提供的所有服务,都是为了帮您更好地学编程、找到理想的工作。诚挚地欢迎您的加入,这可能是最好的学习机会,也是最值得的一笔投资!
长按扫码领优惠券加入体验(三天内不满意可全额退款),也可直接在公众号后台回复客服,添加客服了解更多星球信息:
往期推荐